use crate::config::redis::get_redis_pool;
use crate::model::test::{Test, TestCheck};
use crate::service::common::{Page, PageParams};
use crate::service::test::*;
use crate::state::AppState;
use crate::utils::result::data;
use crate::utils::result::{self, error, info, success};
use axum::response::IntoResponse;
use axum::Extension;
use axum::{
    extract::{Path, Query},
    Form,
};
use axum_valid::Valid;
use redis::AsyncCommands;
use std::collections::HashMap;
use tokio_cron_scheduler::{Job, JobScheduler};

// get 参数 参数可选
pub async fn query(
    Extension(state): Extension<AppState>,
    Query(params): Query<HashMap<String, String>>,
) -> impl IntoResponse {
    let name = match params.get("name") {
        Some(v) => v,
        None => "",
    };
    data(get_by_name(&state.db_pool, &name.to_string()).await, "")
}
// from 参数
pub async fn add(
    Extension(state): Extension<AppState>,
    Form(test): Form<Test>,
) -> impl IntoResponse {
    if add_data(&state.db_pool, test).await {
        success("添加成功")
    } else {
        error("添加失败")
    }
}

pub async fn put(
    Extension(state): Extension<AppState>,
    Form(test): Form<Test>,
) -> impl IntoResponse {
    put_data(&state.db_pool, test).await;
    success("更新成功")
}
// path 参数
pub async fn del(Extension(state): Extension<AppState>, Path(id): Path<i32>) -> impl IntoResponse {
    info(del_data(&state.db_pool, &id).await, "删除成功", "删除失败")
}

pub async fn get_by_id(
    Extension(state): Extension<AppState>,
    Path(id): Path<i32>,
) -> impl IntoResponse {
    data(find_by_id(&state.db_pool, &id).await, "")
}
// 定时任务例子
pub async fn timed_task() -> impl IntoResponse {
    let sched = JobScheduler::new().await.unwrap();
    let job = Job::new("1/10 * * * * *", |uuid, _l| {
        println!("uuid:{}, I run every 10 seconds", uuid);
    })
    .unwrap();
    sched.add(job).await.unwrap();

    // tokio::time::sleep(core::time::Duration::from_secs(100)).await;
    info(
        sched.start().await.is_ok(),
        "开启定时任务成功",
        "开启定时任务失败",
    )
}
/**
 * 使用redis_conn对象时需要是可变的
 * 写入和读取时都需要显式的标注数据类型
 */
// redis 写入
pub async fn set_redis(Path(info): Path<String>,) -> impl IntoResponse {
    let redis_pool = get_redis_pool().await;
    let redis_conn = redis_pool.get().await;
    match redis_conn {
        Ok(mut conn) => {
            let _: () = conn.set("redis_key", info.to_string()).await.unwrap();
            success("写入redis完成")
        }
        Err(_) => error("连接redis发生异常"),
    }
}
// 从redis 读取
pub async fn get_redis() -> impl IntoResponse {
    let redis_pool = get_redis_pool().await;
    let redis_conn = redis_pool.get().await;
    match redis_conn {
        Ok(mut conn) => {
            match conn.get("redis_key").await {
                Ok(Some(value)) => {
                    data(value, "获取值成功")
                }
                Ok(None) => {
                    error("redis中没有该值")
                }
                Err(err) => {
                    println!("{}", err);
                    error("获取值失败")
                }
                
            }
        },
        Err(err) => {
            println!("{}", err);
            error("连接redis发生异常")
        }
    }
}
// 分页
pub async fn list(
    Extension(state): Extension<AppState>,
    Query(page_params): Query<PageParams>,
    Query(p2): Query<HashMap<String, String>>,
) -> impl IntoResponse {
    println!("{:?}", p2);
    // // 如果需要没有id的实体需要另外传入
    let page = Page::new(&state.db_pool, "test".to_string());

    let data = page.list::<Test>(None, page_params).await;
    result::list(data)
}

pub async fn params_check(Valid(Query(test_check)): Valid<Query<TestCheck>>) -> impl IntoResponse {
    result::data(test_check, "参数检查成功")
}
